#ifndef __M_BUFFER_H__
#define __M_BUFFER_H__

#pragma once

#include <iostream>
#include <vector>
#include <cstring>
#include <cstdlib>

#define BUFFER_SIZE 1024

class Buffer
{
private:
    std::vector<char> _buffer;//这里不用string是因为string用c风格字符串读取数据时遇到\0会停止
    uint64_t _reader;
    uint64_t _writer;

public:
    Buffer()
    : _buffer(BUFFER_SIZE),
      _reader(0),
      _writer(0)
    {}

    ~Buffer() {}

    /*
    注意：写偏移永远>=读偏移
    */

    //获取读偏移指向的地址空间
    char* getReaderPosition() { return &_buffer[0] + _reader; }//_buffer起始地址 + _reader
    //获取写偏移指向的地址空间
    char* getWriterPosition() { return &_buffer[0] + _writer; }
    //获取读偏移前的空间大小
    uint64_t getSizeBeforeReader() { return _reader; }
    //获取写偏移后的空间大小
    uint64_t getSizeAfterWriter() { return _buffer.size() - _writer; }
    //获取可读空间大小
    uint64_t getAbleReadSize() { return _writer - _reader; }
    //获取可写空间大小
    uint64_t getAbleWriteSize() { return getSizeBeforeReader() + getSizeAfterWriter(); }
    //读偏移向后移动
    void moveReader(uint64_t size)//size为要读取的数据大小
    {
        if (getAbleReadSize() < size)//要读取的数据大小超过了可读数据大小
        {
            LOG(ERR, "the able read size is not enough");
            exit(-1);
        }
        _reader += size;
    }
    //写偏移向后移动
    void moveWriter(uint64_t size)//size为要写入的数据大小
    {
        if (getSizeAfterWriter() < size)//写偏移后的空间不够移动
        {
            LOG(ERR, "the size after writer is not enough");
            exit(-1);
        }
        _writer += size;
    }
    //读取数据
    bool Read(void* buf, uint64_t size)
    {
        if (size <= 0)
            return false;
        if (_reader + size > _writer)//确保可读空间足够
        {
            LOG(ERR, "the able read size is not enough");
            return false;
        }
        std::copy(getReaderPosition(), getReaderPosition() + size, (char*)buf);
        moveReader(size);//移动读偏移
        return true;
    }

    bool ReadAsString(std::string& buf, uint64_t size) 
    { 
        buf.resize(size);
        return Read(&buf[0], size);
    }

    bool ReadAsBuffer(Buffer& buf, uint64_t size)
    {
        bool ret = Read(buf.getWriterPosition(), size);
        buf.moveWriter(size);
        return ret;
    }
    //写入数据
    bool Write(const void* data, uint64_t size)
    {
        if (size <= 0)
            return false;
        makeAbleWrite(size);
        std::copy((const char*)data, (const char*)data + size, getWriterPosition());
        moveWriter(size);
        return true;
    }

    bool WriteString(const std::string& s) { return Write(s.c_str(), s.size()); }

    bool WriteBuffer(Buffer& buf) { return Write(buf.getReaderPosition(), buf.getAbleReadSize()); }

    //读取一行数据
    std::string getLine()
    {
        //找到Buffer的换行位置
        char* pos = (char*)memchr(getReaderPosition(), '\n', getAbleReadSize());
        if (pos == nullptr)
            return "";
        std::string ret;
        if (!ReadAsString(ret, pos - getReaderPosition() + 1))//+1是为了将换行字符读取到string中
            return "";
        return ret;
    }

    //一个buffer要写入另一个buffer 直接让另一个buffer调用ReadAsBuffer即可

    //保证有足够的可写空间来写入数据
    void makeAbleWrite(uint64_t size)
    {
        if (getSizeAfterWriter() >= size)//写偏移之后的空间的大小 >= size 不用进行额外处理
            return;
        if (getAbleWriteSize() >= size)//读偏移之前的空间大小 + 写偏移之后的空间的大小 >= size
        {
            std::copy(getReaderPosition(), getWriterPosition(), _buffer.begin());
            uint64_t ableReadSize = getAbleReadSize();
            _reader = 0;
            _writer = _reader + ableReadSize;
        }
        else//读偏移之前的空间大小 + 写偏移之后的空间的大小 < size
        {
            //直接在_buffer末尾添加相应大小的空间 而不是扩容size - AbleWriteSize大小 省去拷贝数据的工作
            _buffer.resize(_buffer.size() + size);
        }
    }
    //清空Buffer
    void Clear() { _reader = _writer = 0; }
};

#endif
